package ru.btabank.dom.xpath.expression;

import org.w3c.dom.Node;

public abstract class NameStep extends Step {
    private String localName;

    private String prefix;

    private String namespaceURI;

    private boolean matchesAnyLocalName;

    private boolean matchesAnyPrefix;

    private boolean hasNoPrefix;

    public NameStep(String prefix, String localName, String namespaceURI) {
        this.localName = localName;
        this.prefix = prefix;
        this.namespaceURI = namespaceURI;
        this.hasNoPrefix = this.prefix == null || this.prefix.length() == 0;
        this.matchesAnyPrefix = "*".equals(this.prefix);
        this.matchesAnyLocalName = "*".equals(this.localName);
    }

    protected String getNamespaceURI() {
        return this.namespaceURI;
    }

    protected String getLocalName() {
        return this.localName;
    }

    protected String getName() {
        if (hasNoPrefix())
            return this.localName;
        else
            return this.prefix + ":" + this.localName;
    }
    
    protected boolean hasNoPrefix() {
        return this.hasNoPrefix;
    }

    protected boolean matchesAnyPrefix() {
        return this.matchesAnyPrefix;
    }

    protected boolean matchesAnyLocalName() {
        return this.matchesAnyLocalName;
    }

    protected boolean matches(Node node) {
        if (this.matchesAnyLocalName()) {

            if (this.hasNoPrefix())
                // * - matches any node
                return true;

            else
                // NCName:* - matches any node with any local name and prefix 'NCName'
                return this.getNamespaceURI().equals(node.getNamespaceURI());

        } else if (this.getLocalName().equals(node.getLocalName())) {

            if (this.hasNoPrefix())
                // NCName - matches any node whose local name is NCName and prefix is null
                return node.getNamespaceURI() == null;

            else if (this.matchesAnyPrefix())
                // *:NCName - matches any node whose local name is NCName regardless of its prefix
                return true;

            else
                // NCName:NCName - matches any node whose local name is NCName and prefix is NCName
                return this.getNamespaceURI().equals(node.getNamespaceURI());

        } else

            // Node does not match
            return false;
    }
}
